package ch.zhaw.cctd.gui;

import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.plaf.synth.SynthLookAndFeel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.zhaw.cctd.domain.DomainFacade;
import ch.zhaw.cctd.logic.network.NetworkException;
import ch.zhaw.cctd.logic.util.ConfigHandler;
import ch.zhaw.cctd.logic.xml.XmlReadException;

/**
 * Ist die JFrame Implementation und bietet die primären
 * Spielvorbereitungsaktionen für den Spieler. Ruft die benötigten Klassen für
 * den Ablauf auf.
 * 
 * @author Lukas Spirig
 */
public class CCTDFrame extends JFrame {

	private static final long serialVersionUID = 2993357989476454697L;

	private static final Logger logger = LoggerFactory.getLogger(CCTDFrame.class);

	public final static String GRAPHICS_PATH = "../graphics/";
	public final static String LAF_PATH = "laf/";
	public final static int REFRESH_RATE = 1000/60;
	public final static int NAME_LENGTH = 22;

	private String userName = "";
	private boolean isHost = false;

	private String xml;

	private StartGUI startGUI;
	private LobbyGUI lobbyGUI;
	private MatchGUI matchGUI;
	private MenuGUI menuGUI;
	private JWindow overlay;

	public CCTDFrame() {
		this(ConfigHandler.getInstance().getConfigValue(ConfigHandler.CFG_PAR_XML));
	}

	public CCTDFrame(String xml) {
		this(xml, ConfigHandler.getInstance().getConfigValue(ConfigHandler.CFG_PAR_RES));
	}

	public CCTDFrame(String xml, String resolution) {
		try {
			SynthLookAndFeel laf = new SynthLookAndFeel();
			laf.load(CCTDFrame.class.getResource(CCTDFrame.LAF_PATH + "cctd_laf.xml"));
			UIManager.setLookAndFeel(laf);
			//UIManager .setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		} catch (Exception e) {
			
			logger.error(e.getMessage());
		}

		this.xml = xml;
		// Check if the Ressource exists
		if (this.getClass().getResourceAsStream(this.xml) == null)
			this.xml = "/ch/zhaw/cctd/xml/cctd.xml";

		int width, height;
		// Check if the Config Parameters are in the right form
		if (resolution.matches("\\d*x\\d*")) {
			String[] res = resolution.split("x");
			width = Integer.parseInt(res[0]);
			height = Integer.parseInt(res[1]);
		} else {
			width = 1024;
			height = 768;
		}
		this.setSize(width, height);
		this.setTitle("Circle Cube Tower Defense");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setResizable(true);

		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				quitGame();
			}
		});

		startGUI = new StartGUI(this);
		// Overlay Window that disables the Main Window
		overlay = new JWindow(this);
		overlay.setVisible(false);
		menuGUI = new MenuGUI(this);
		this.start();
	}

	public void setUsername(String username) {
		this.userName = username;
	}

	public boolean isSetUsername() {
		return (!userName.equals(""));
	}
	
	@Override
	public void setEnabled(boolean arg0) {
		if(!arg0) {
			overlay.setSize(this.getWidth(), this.getHeight());
			overlay.setLocation(this.getLocation());
			overlay.setBackground(Color.LIGHT_GRAY);
			overlay.setVisible(true);
		} else {
			overlay.setVisible(false);
		}
		super.setEnabled(arg0);
	}
	
	public void start() {
		isHost = false;
		startGUI.start();
	}

	public void quitGame() {
		if (lobbyGUI != null)
			lobbyGUI.stopEventListener();
		if (matchGUI != null)
			matchGUI.stopThreads();
		DomainFacade.quitGame();
		System.exit(0);
	}

	public void leaveGame() {
		if (lobbyGUI != null)
			lobbyGUI.stopEventListener();
		if (matchGUI != null)
			matchGUI.stopThreads();
		DomainFacade.leaveGame();
	}

	public void createGame() {
		try {
			InputStream stream = this.getClass().getResourceAsStream(this.xml);
			DomainFacade.startHostedGame(stream);
		} catch (NetworkException e) {
			e.printStackTrace();
		} catch (XmlReadException e) {
			e.printStackTrace();
		}
		isHost = true;
		try {
			DomainFacade.joinGame(InetAddress.getLocalHost().getHostName(), userName);
			lobbyGUI = new LobbyGUI(this);
			lobbyGUI.start();
		} catch (UnknownHostException e) {
			logger.error(e.getMessage());
		} catch (NetworkException e) {
			logger.error(e.getMessage());
		}

	}

	public void joinGame(String address) {
		try {
			DomainFacade.joinGame(address, userName);
			isHost = false;
			lobbyGUI = new LobbyGUI(this);
			lobbyGUI.start();
		} catch (NetworkException e) {
			error("Verbindungsfehler", "Verbindung zum Server nicht möglich.");
		}

	}

	public void error(String title, String string) {
		logger.error(string);
		JOptionPane.showMessageDialog(this, string, title, JOptionPane.ERROR_MESSAGE);
	}
	
	public void message(String title, String string) {
		logger.trace(string);
		JOptionPane.showMessageDialog(this, string, title, JOptionPane.INFORMATION_MESSAGE);
	}

	public void playMatch() {
		matchGUI = new MatchGUI(this);

		matchGUI.start();
	}

	public MenuGUI getMenuGUI() {
		return menuGUI;
	}

	public boolean isHost() {
		return isHost;
	}

	public String getUserName() {
		return userName;
	}
}
